import * as Cesium from 'cesium'

const testVertex = `
  in vec3 position3DHigh;
  in vec3 position3DLow;
  in float batchId;
  in vec4 color;
  in vec3 position;
  out vec4 v_color;
  out float vElevation;

  void main() {
    float time = czm_frameNumber / 60.0;
    vec4 modelPosition = vec4(position, 1.0);
    modelPosition.y += sin((modelPosition.x) * 3.0 + time) * 100000.0;
    modelPosition.y += sin((modelPosition.z) * 3.0 + time) * 100000.0;
    vElevation = modelPosition.y;
    v_color = color;
    gl_Position = czm_projection * czm_modelView * modelPosition;
  }
`

const testFrag = `
  in vec4 v_color;
  in float vElevation;
  uniform vec2 iResolution;
  precision mediump float;
  out vec4 myFragColor;

  void main() {
    float time = fract(czm_frameNumber / 60.0);
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    float elevation = vElevation * 0.5 + 0.5;
    vec3 color = vec3(1.0 * elevation, 0.0, 0.0);
    myFragColor= vec4(color, 1.0);
    // myFragColor = vec4(1.0, 1.0, 0.0, 1.0);
  }
`
export default class WavePrimitive {
  constructor() {
    this.drawCommand = null
  }
  /**
   * 将经纬度坐标转换为笛卡尔坐标
   * @param {*} i 列索引
   * @param {*} j 航索引
   * @returns [pos.x, pos.y, pos.z]
   */
  transformPos(lonlat, height = 300000.0) {
      let pos = Cesium.Cartesian3.fromDegrees(...lonlat, height)
      return [pos.x, pos.y, pos.z]
  }
  /**
   * 根据坐标中心点生成周围四个点坐标
   * @param {*} v1 
   * @param {*} v2 
   * @returns 
   */
  addVector(v1, v2) {
    return [v1[0] + v2[0], v1[1] + v2[1]]
  }
  /**
   * 根据自定义Geometry生成Primitive对象
   * @returns {Cesium.Primitive}
   */
  generateWaveGeometry() {
    const geometry = Cesium.BoxGeometry.createGeometry(new Cesium.BoxGeometry({
      vertexFormat : Cesium.VertexFormat.POSITION_ONLY,
      maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0),
      minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0)
    }))
    /**
     * 创建将属性名称映射到唯一位置（索引）的对象 用于匹配顶点属性和着色器程序。
     * { position: 0, normal: 1, st: 2, bitangent: 3, tangent: 4, color: 5 }
     */
    console.log(Cesium.GeometryPipeline.createAttributeLocations(geometry))
    return geometry
  }
  /**
   * 创建DrawCommand对象，用于渲染Primitive对象。
   * @param {*} context 
   */
  createDrawCommand(context) {
    let geometry = this.generateWaveGeometry()
    let vertexArray = Cesium.VertexArray.fromGeometry({
      context: context,
      geometry: geometry,
      attributeLocations: Cesium.GeometryPipeline.createAttributeLocations(geometry)
    })
    let shaderProgram = Cesium.ShaderProgram.fromCache({
      context: context,
      vertexShaderSource: testVertex,
      fragmentShaderSource: testFrag,
      attributeLocations: Cesium.GeometryPipeline.createAttributeLocations(geometry)
    })
    let uniformMap = {
      iResolution() {
        return new Cesium.Cartesian2(context.canvas.width, context.canvas.height)
      }
    }
    let renderState = Cesium.RenderState.fromCache({
      depthTest: {
        enabled: true,
      },
      depthMask: false,
      blending: Cesium.BlendingState.ALPHA_BLEND,
    })
    this.drawCommand = new Cesium.DrawCommand({
      vertexArray: vertexArray,
      shaderProgram: shaderProgram,
      renderState: renderState,
      uniformMap: uniformMap,
      pass: Cesium.Pass.OPAQUE,
      castShadows: false,
      receiveShadows: false,
      primitiveType: Cesium.PrimitiveType.TRIANGLES,
      // 设置模型的位置，这个是固定位置
      modelMatrix : Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(117.0, 36.0))
    })
  }
  /**
   * 更新Primitive对象，将其添加到渲染队列中。
   * @param {*} framestate 
   */
  update(framestate) {
    if(this.drawCommand === null) {
      this.createDrawCommand(framestate.context)
    }
    framestate.commandList.push(this.drawCommand)
  }
}
